package com.jetpack.mvvm.lib.net.module

import okhttp3.Headers


sealed class HttpApiResult<out T>(open val responseHeader: Headers?) : java.io.Serializable {
    val isSuccess: Boolean get() = this is Success
    val isFailure: Boolean get() = this !is Success

    data class Success<T : Any>(val value: T, override val responseHeader: Headers?) :
        HttpApiResult<T>(responseHeader) {
        override fun toString(): String {
            return "Success($value)"
        }

        override fun exceptionOrNull(): Throwable? = null
    }

    data class HttpApiError(
        val code: Int = -1,
        val message: String? = null,
        val throwable: Throwable,
        override val responseHeader: Headers? = null,
    ) :
        HttpApiResult<Nothing>(responseHeader) {
        override fun toString(): String {
            return "ApiError(message:$message,code:$code)"
        }

        override fun exceptionOrNull(): Throwable = throwable
    }

    data class NetworkError(
        val error: Throwable,
        override val responseHeader: Headers? = null,
    ) : HttpApiResult<Nothing>(responseHeader) {
        override fun toString(): String {
            return "NetworkError(error:${error.message})"
        }

        override fun exceptionOrNull(): Throwable = error
    }

    data class UnknownError(
        val throwable: Throwable?,
        override val responseHeader: Headers? = null,
    ) : HttpApiResult<Nothing>(responseHeader) {
        override fun toString(): String {
            super.toString()
            return "UnknownError(throwable:${throwable?.message})"
        }

        override fun exceptionOrNull(): Throwable? = throwable
    }

    fun getOrNull(): T? = (this as? Success)?.value

    open fun exceptionOrNull(): Throwable? = null

    companion object {
        fun <T : Any> success(result: T, responseHeader: Headers?): HttpApiResult<T> =
            Success(result, responseHeader)

        fun apiError(
            code: Int = -1,
            message: String? = null,
            throwable: Throwable,
            responseHeader: Headers?
        ): HttpApiResult<Nothing> =
            HttpApiError(code, message, throwable, responseHeader)

        fun <Nothing> networkError(
            error: Throwable, responseHeader: Headers?
        ): HttpApiResult<Nothing> =
            NetworkError(error, responseHeader)

        fun <Nothing> unknownError(
            throwable: Throwable?, responseHeader: Headers?
        ): HttpApiResult<Nothing> =
            UnknownError(throwable, responseHeader)
    }

}